
#pragma once

#include "Half.h"
#include "ImfIO.h"
#include "Iex.h"
#include "ImfOutputFile.h"
#include "ImfInputFile.h"
#include "ImfRgbaFile.h"
#include "ImfChannelList.h"
#include "ImfRgba.h"
#include "ImfArray.h"
#include "ImfPreviewImage.h"

using namespace System;
using namespace System::Collections::Generic;
using namespace System::IO;

using namespace Derm::Raster;

namespace Derm {

	/// <summary>
	/// Managed plugin wrapping OpenEXR library.
	/// </summary>
	ref class OpenEXRImageCodecPlugin : ImageCodecPlugin
	{
#pragma region EXR Format Management

	private:

		static Pixel::Type GetPixelTypeFromChannels(const Imf::ChannelList &channels);

#pragma endregion

#pragma region IImageCodecPlugin Implementation

	public:

		/// <summary>
		/// Determine whether this plugin is available for the current process.
		/// </summary>
		/// <returns>
		/// It returns a boolean value indicating whether the plugin is available for the current
		/// process.
		/// </returns>
		virtual bool CheckAvailability() override;

		/// <summary>
		/// Plugin name.
		/// </summary>
		/// <remarks>
		/// This name identity the plugin implementation. It shall be unique in the plugin set available at
		/// runtime.
		/// </remarks>
		virtual property String ^Name
		{
			String ^ get() override {
				return (gcnew String("Derm.OpenEXR"));
			}
		}

		/// <summary>
		/// Query image file informations.
		/// </summary>
		/// <returns>
		/// A <see cref="ImageInfo"/>
		/// </returns>
		virtual ImageInfo ^QueryImageInfo(Stream ^fs, ImageCodec::CodecCriteria ^criteria) override;

		/// <summary>
		/// Load image from file.
		/// </summary>
		/// <param name="fs">
		/// A <see cref="FileStream"/> where the image data is stored.
		/// </param>
		/// <param name="criteria">
		/// A <see cref="ImageCodec.CodecCriteria"/> specifying parameters for loading an image stream.
		/// </param>
		/// <returns>
		/// An <see cref="Image"/> holding the image data.
		/// </returns>
		virtual Image ^Load(Stream ^fs, ImageCodec::CodecCriteria ^criteria) override;

		/// <summary>
		/// Save image pixels to file.
		/// </summary>
		/// <param name="fs">
		/// A <see cref="System.IO.FileStream"/> which stores the image data.
		/// </param>
		/// <param name="image">
		/// A <see cref="Image"/> holding the data to be stored.
		/// </param>
		/// <param name="criteria">
		/// A <see cref="ImageCodec.CodecCriteria"/> specifying parameters for loading an image stream.
		/// </param>
		virtual void Save(Stream ^fs, Image ^image, ImageFormat format, ImageCodec::CodecCriteria ^criteria) override;

		/// <summary>
		/// Get a list of image formats supported for reading.
		/// </summary>
		virtual property IEnumerable<ImageFormat> ^SupportedReadImageFormats
		{
			IEnumerable<ImageFormat> ^get() override {
				List<ImageFormat> ^formats = gcnew List<ImageFormat>();

				formats->Add(ImageFormat::Exr);

				return (formats);
			}
		}

		/// <summary>
		/// Get a list of image formats supported for writing.
		/// </summary>
		virtual property IEnumerable<ImageFormat> ^SupportedWriteImageFormats
		{
			IEnumerable<ImageFormat> ^get() override {
				return (gcnew List<ImageFormat>());
			}
		}

#pragma endregion
	};

}
